<!-- 巅峰人才榜 童晓白 2025-07-25	-->
<template>
  <view class="apex-page">
    <view class="apex-content-card">
    <!-- 筛选区 -->
    <section class="apex-filters">
        <view class="apex-info-card">
          <view class="apex-select-row">
            <Select v-model="selectedProvince" :options="provinces" placeholder="选择省份" @change="onProvinceChange" class="apex-select" />
            <Select v-model="selectedCity" :options="cities" placeholder="选择城市" @change="onCityChange" class="apex-select" />
            <Select v-model="selectedDistrict" :options="districts" placeholder="选择区县" @change="onDistrictChange" class="apex-select" />
      </view>
          <view class="apex-select-row">
            <Select v-model="selectedField" :options="fieldsOptions" placeholder="选择领域" @change="onFieldChange" class="apex-select" />
            <Select v-model="selectedCategory" :options="categoryList" placeholder="选择大类" @change="onCategoryChange" class="apex-select" />
            <Select v-model="selectedDirection" :options="directions" placeholder="选择方向" @change="fetchRanking" class="apex-select" />
      </view>
          <view class="apex-time-row">
            <text class="apex-time-label">时间筛选：</text>
          <picker
            mode="multiSelector"
            :range="dateTimeArray"
            :value="dateTimeIndex"
            @change="onStartDateTimeChange"
              class="apex-date-btn"
          >
            <view class="picker-text">{{ filters.startPublishTime || '开始时间' }}</view>
          </picker>
          <text class="apex-date-separator">至</text>
          <picker
            mode="multiSelector"
            :range="dateTimeArray"
            :value="dateTimeIndex"
            @change="onEndDateTimeChange"
              class="apex-date-btn"
          >
            <view class="picker-text">{{ filters.endPublishTime || '结束时间' }}</view>
          </picker>
        </view>
      </view>
    </section>
    <!-- 排行榜表格 -->
    <section class="apex-table-wrapper">
        <view class="apex-table-header">
          <view>排名</view>
          <view>贡献者</view>
          <view>角色</view>
          <view>方向</view>
          <view>任务ID</view>
        </view>
        <view
          v-for="(row, idx) in ranking"
          :key="row.badgeId + '-' + row.contributorUid"
          class="apex-table-row"
        >
          <view>{{ (page - 1) * pageSize + idx + 1 }}</view>
          <view class="apex-user" @tap.stop="goToProfile(row.contributorUid)">
            <image :src="row.avatar_url" class="apex-avatar" />
            <view class="apex-user-info">
              <text class="apex-nickname">{{ row.nickname }}</text>
              <text class="apex-user-lv">lv: {{ row.level }}</text>
            </view>
          </view>
          <view>{{ row.contributorRole || '-' }}</view>
          <view class="apex-direction">{{ getBadgeName(row.association) }}</view>
          <view class="apex-taskid" @tap.stop="handleRowClick(row)" style="cursor:pointer;color:#00eaff;">{{ row.taskId }}</view>
      </view>
    </section>
      <!-- 分页栏 -->
    <nav class="apex-pagination">
        <button class="apex-page-btn" :disabled="page<=1" @tap="handlePageChange(page-1)">上一页</button>
      <text class="apex-page-info">第 {{ page }} 页 / 共 {{ Math.ceil(total/pageSize) }} 页</text>
        <button class="apex-page-btn" :disabled="page>=Math.ceil(total/pageSize)" @tap="handlePageChange(page+1)">下一页</button>
    </nav>
    </view>

    <!-- 词云 -->
    <section v-if="wordcloudData" class="wordcloud-section">
      <view class="section-title">词云</view>
      <qiun-data-charts
        type="wordCloud"
        :opts="wordCloudOpts"
        :chartData="wordCloudChartData"
        canvasId="wordcloud"
        style="width: 100%; height: 320px;"
      />
    </section>
  </view>
</template>

<script setup>
import { ref, onMounted, computed } from 'vue'

import { geoData, getAdcodeByDistrict } from '@/utils/geoUtils'
import { categories, getBadgeNameByAssociation } from '@/utils/skillUtils'
import { NETWORK_CONFIG } from '@/config/network.js'
import Select from './Select.vue'
import BackButton from '../../components/BackButton.vue'
import QiunDataCharts from '@/components/qiun-data-charts/qiun-data-charts.vue'


const ranking = ref([])
const loading = ref(false)
const total = ref(0)
const page = ref(1)
const pageSize = ref(10)

const today = new Date().toISOString().split('T')[0]
const lastYear = new Date()
lastYear.setFullYear(lastYear.getFullYear() - 1)

const filters = ref({
  startDate: lastYear.toISOString().split('T')[0],
  startTime: '00:00',
  endDate: '',
  endTime: '23:59'
})

// 地区分类相关
const provinces = ref(geoData.map((province) => province.name))
const selectedProvince = ref('')
const cities = ref([])
const selectedCity = ref('')
const districts = ref([])
const selectedDistrict = ref('')
const selectedAdCode = ref('')

// 技能分类相关
const fieldsOptions = computed(() => categories.map(f => ({ label: f.name, value: f.code })))
const fields = ref(categories)
const selectedField = ref('')
const selectedCategory = ref('')
const selectedDirection = ref('')
const categoryList = ref([])
const directions = ref([])

const dateTimeArray = ref([])
const dateTimeIndex = ref([0, 0, 0])

const initDateTimeArray = () => {
  const date = new Date()
  const years = []
  const months = []
  const days = []
  // 生成年份（前后5年）
  for (let i = date.getFullYear() - 5; i <= date.getFullYear() + 5; i++) {
    years.push(i + '年')
  }
  // 生成月份
  for (let i = 1; i <= 12; i++) {
    months.push(i + '月')
  }
  // 生成日期
  for (let i = 1; i <= 31; i++) {
    days.push(i + '日')
  }
  dateTimeArray.value = [years, months, days]
}

const formatDateTime = (date) => {
  if (!date) return ''
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  return `${year}-${month}-${day} ${hours}:${minutes}`
}

const formatDateTimeForAPI = (date) => {
  if (!date) return null
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  return `${year}-${month}-${day}T${hours}:${minutes}:00`
}

const onStartDateTimeChange = (e) => {
  const values = e.detail.value
  const year = parseInt(dateTimeArray.value[0][values[0]])
  const month = parseInt(dateTimeArray.value[1][values[1]])
  const day = parseInt(dateTimeArray.value[2][values[2]])
  filters.value.startPublishTime = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`
  fetchRanking()
}

const onEndDateTimeChange = (e) => {
  const values = e.detail.value
  const year = parseInt(dateTimeArray.value[0][values[0]])
  const month = parseInt(dateTimeArray.value[1][values[1]])
  const day = parseInt(dateTimeArray.value[2][values[2]])
  filters.value.endPublishTime = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`
  fetchRanking()
}

const updateCities = () => {
  const province = geoData.find((p) => p.name === selectedProvince.value)
  if (province) {
    cities.value = province.cities.map((city) => city.name)
  } else {
    cities.value = []
  }
  selectedCity.value = ''
  districts.value = []
  selectedDistrict.value = ''
  getSelectedAdcode()
}

const updateDistricts = () => {
  const province = geoData.find((p) => p.name === selectedProvince.value)
  const city = province?.cities.find((c) => c.name === selectedCity.value)
  if (city) {
    districts.value = city.districts.map((district) => district.name)
  } else {
    districts.value = []
  }
  selectedDistrict.value = ''
  getSelectedAdcode()
}

const getSelectedAdcode = () => {
  let adCode = ''
  if (selectedDistrict.value) {
    adCode = getAdcodeByDistrict(selectedDistrict.value)
  } else if (selectedCity.value) {
    const province = geoData.find((p) => p.name === selectedProvince.value)
    const city = province?.cities.find((c) => c.name === selectedCity.value)
    if (city) adCode = city.adcode
  } else if (selectedProvince.value) {
    const province = geoData.find((p) => p.name === selectedProvince.value)
    if (province) adCode = province.adcode
  }
  selectedAdCode.value = adCode
}

const updateCategoryList = () => {
  const field = fields.value.find((f) => f.code === selectedField.value)
  if (field) {
    categoryList.value = field.subcategories.map((category) => ({
      label: category.name,
      value: category.code
    }))
  } else {
    categoryList.value = []
  }
  selectedCategory.value = ''
  directions.value = []
  selectedDirection.value = ''
}

const updateDirections = () => {
  const field = fields.value.find((f) => f.code === selectedField.value)
  const category = field?.subcategories.find((c) => c.code === selectedCategory.value)
  if (category) {
    directions.value = category.directions.map((direction) => ({
      label: direction.name,
      value: direction.code
    }))
  } else {
    directions.value = []
  }
  selectedDirection.value = ''
}

const getBadgeName = (association) => {
  return getBadgeNameByAssociation(association)
}

const fetchRanking = async () => {
  loading.value = true
  try {
    const params = {}
    if (selectedAdCode.value) params.adCode = selectedAdCode.value
    if (selectedDirection.value || selectedCategory.value || selectedField.value) {
      params.association = selectedDirection.value || selectedCategory.value || selectedField.value
    }
    if (filters.value.startPublishTime) {
      params.startPublishTime = formatDateTimeForAPI(new Date(filters.value.startPublishTime.replace(/-/g, '/')))
    }
    if (filters.value.endPublishTime) {
      params.endPublishTime = formatDateTimeForAPI(new Date(filters.value.endPublishTime.replace(/-/g, '/')))
    }
    params.page = page.value - 1
    params.size = pageSize.value

    const requestUrl = `${NETWORK_CONFIG.API_BASE_URL}/badge/ranking`
    console.log('请求URL:', requestUrl)
    console.log('请求参数:', params)
    
    const res = await uni.request({
      url: requestUrl,
      method: 'GET',
      data: params
    })
    console.log('响应数据:', res.data)
    
    const data = res.data;
    if (!data || !Array.isArray(data.content)) {
      console.error('响应数据格式错误:', data)
      handleError('获取排行数据失败');
      return;
    }
    ranking.value = data.content;
    total.value = data.totalElements;
  } catch (e) {
    console.error('获取排行数据异常:', e)
    handleError('获取排行数据失败')
  } finally {
    loading.value = false
  }
}

const handlePageChange = (val) => {
  page.value = val
  fetchRanking()
}

// 地区分类change事件
const onProvinceChange = () => {
  updateCities()
  fetchRanking()
}
const onCityChange = () => {
  updateDistricts()
  fetchRanking()
}
const onDistrictChange = () => {
  getSelectedAdcode()
  fetchRanking()
}
// 技能分类change事件
const onFieldChange = () => {
  updateCategoryList()
  fetchRanking()  
}
const onCategoryChange = () => {
  updateDirections()
  fetchRanking()  
}

// 跳转到个人主页
const goToProfile = (uid) => {
  if (!uid) return;
  uni.setStorageSync('routeUid', uid); // 存储目标用户uid
  uni.switchTab({ url: '/pages/profile/index' }); // 跳转tabbar个人主页
}

// 跳转到association页面
const handleRowClick = (row) => {
  if (!row.contributorUid || !row.badgeId) return
  uni.navigateTo({
    url: `/pages/skill-tree/association/index?contributorId=${row.contributorUid}&badges=${row.badgeId}`,
    fail: (err) => {
      console.error('跳转到关联详情页面失败:', err)
      handleError('页面跳转失败')
    }
  })
}

function formatDate(dateStr) {
  if (!dateStr) return ''
  const d = new Date(dateStr)
  return d.toLocaleString('zh-CN', { hour12: false })
}

const handleError = (message) => {
  uni.showToast({
    title: message,
    icon: 'none',
    duration: 2000
  })
}

const handleSuccess = (message) => {
  uni.showToast({
    title: message,
    icon: 'success',
    duration: 2000
  })
}

onMounted(() => {
  initDateTimeArray()
  fetchRanking()
})

// 计算属性处理词云数据
const wordcloudData = ref(null)
const wordCloudChartData = computed(() => {
  if (!wordcloudData.value) return { series: [] }
  return {
    series: Object.entries(wordcloudData.value).map(([name, value]) => ({
      name,
      textSize: 16 + Math.random() * 24,
      color: `rgb(${Math.round(Math.random()*160)},${Math.round(Math.random()*160)},${Math.round(Math.random()*160)})`,
      value
    }))
  }
})
const wordCloudOpts = {}
</script>

<style scoped>
.apex-page {
  width: 100vw;
  min-height: 100vh;
  background: #f5f5f5;
  box-sizing: border-box;
  padding-bottom: 70px;
}
.apex-filters {
  background: transparent;
  margin-bottom: 12px;
  padding: 0;
}
.apex-info-card {
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(74,144,226,0.08);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.apex-select-row {
  display: flex;
  flex-wrap: nowrap;
  gap: 12px;
  margin-bottom: 0;
}
.apex-select {
  flex: 1 1 0;
  min-width: 0;
  max-width: 100%;
}
.apex-time-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
  flex-wrap: wrap;
}
.apex-time-label {
  color: #4A90E2;
  font-weight: bold;
  font-size: 15px;
  margin-right: 6px;
}
.apex-date-btn {
  background: #fff;
  color: #4A90E2;
  border: 1.5px solid #4A90E2;
  border-radius: 8px;
  font-size: 15px;
  font-weight: bold;
  padding: 8px 12px;
  min-width: 0;
  width: 100%;
  box-sizing: border-box;
  height: 36px;
  transition: border 0.2s, background 0.2s;
}
.apex-date-btn:focus {
  border: 1.5px solid #3578c6;
  background: #eaf4fd;
}
.picker-text {
  color: #4A90E2;
  font-weight: bold;
  font-size: 15px;
}
.apex-date-separator {
  color: #4A90E2;
  font-weight: bold;
  font-size: 15px;
  margin: 0 4px;
}
.apex-table-wrapper {
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(74,144,226,0.06);
  padding: 8px 0;
  margin-bottom: 12px;
}
.apex-table {
  width: 100%;
  border-radius: 12px;
  overflow: hidden;
}
.apex-table-header, .apex-table-row {
  display: grid;
  grid-template-columns: 0.7fr 1.8fr 1.5fr 2.2fr 1fr;
  align-items: center;
  font-size: 15px;
  min-height: 36px;
  padding: 8px 12px;
  column-gap: 18px;
}
.apex-table-header {
  background: #4A90E2;
  color: #f5f5f5;
  font-weight: bold;
  border-bottom: 2px solid #e0e0e0;
}
.apex-table-row {
  background: #fff;
  color: #333;
  font-size: 14px;
  border-bottom: 1px solid #f0f0f0;
}
.apex-user {
  display: flex;
  align-items: center;
  gap: 8px;
}
.apex-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid #e0e0e0;
  object-fit: cover;
  background: #fff;
}
.apex-user-info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: 0;
}
.apex-nickname {
  color: #4A90E2;
  font-weight: bold;
  font-size: 15px;
}
.apex-user-lv {
  font-size: 12px;
  color: #888;
  margin-top: 2px;
}
.apex-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 16px 0 0 0;
  gap: 18px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(74,144,226,0.06);
  padding: 8px 0;
}
.apex-page-btn {
  background: #4A90E2;
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: 0 16px;
  height: 32px;
  font-size: 15px;
  font-weight: bold;
  margin: 0 4px;
  transition: background 0.2s;
}
.apex-page-btn:disabled {
  background: #e0e0e0;
  color: #aaa;
  cursor: not-allowed;
}
.apex-page-info {
  color: #4A90E2;
  font-size: 15px;
  font-weight: bold;
  letter-spacing: 1px;
}
.wordcloud-section {
  background: #141e32;
  border-radius: 12px;
  margin-bottom: 32px;
  padding: 32px 16px;
}
.apex-select-inner {
  background: #fff;
  color: #4A90E2;
  border: 1.5px solid #4A90E2;
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 15px;
  font-weight: bold;
  outline: none;
  min-width: 0;
  width: 100%;
  box-sizing: border-box;
  transition: border 0.2s, background 0.2s;
  height: 36px;
}
.apex-select-inner:focus {
  border: 1.5px solid #3578c6;
  background: #eaf4fd;
}
.apex-select-row .apex-select {
  flex: 1 1 0;
  min-width: 0;
  max-width: 100%;
}
.apex-time-row .apex-date-btn {
  flex: 1 1 0;
  min-width: 0;
  max-width: 100%;
}
@media (max-width: 480px) {
  .apex-select-inner,
  .apex-date-btn {
    font-size: 13px;
    padding: 4px 6px;
    height: 28px;
    border-radius: 6px;
  }
}
</style>
